#include "Fluid.h"
#include <time.h>

#define RAND ((qreal)qrand()/RAND_MAX)
#define MAX(a,b) ((a)>(b)?(a):(b))

Fluid::Fluid() : Object3D() , boxm(QVector3D(-0.1, -0.1, -0.2)), boxM(QVector3D(0.1, 0.1, 0.2))
{
    qreal Xm = boxm.x() ;
    qreal XM = boxM.x() ;
    qreal Ym = boxm.y() ;
    qreal YM = boxM.y() ;
    qreal off = (boxM.z() - boxm.z())/4;
    qreal Zm = boxm.z() +  off ;
    qreal ZM = (boxM.z() + boxm.z() )/2 + off ;

    int   nx =   20;
    int   ny =   20;
    int   nz =   20;

    qreal dx = (XM-Xm)/nx;
    qreal dy = (YM-Ym)/ny;
    qreal dz = (ZM-Zm)/nz;
    qreal v = dx*dy*dz;
    qreal h = MAX(dx, MAX(dy,dz))*1.1;
    qreal x = Xm;
	int idx = 0;
    for(int i = 0; i < nx+1; ++i, x+=dx)
    {
        qreal y = Ym;
        for(int j = 0; j < ny+1; ++j, y+=dy)
        {
            qreal z =  Zm;
            for(int k = 0; k < nz+1; ++k, z+= dz)
            {
				Particle *p = new Particle(idx++, QVector3D(x,y,z));
                p->mass() = 1e3*v;
                particles.push_back(p);
            }
        }
    }

    engine = new SPHEngine(particles, &boxm, &boxM, h);
    engine->begin();
}

void Fluid::drawGeometry(void)
{
    drawBox();
    glPointSize(3.0);
    glDisable(GL_LIGHTING);
    glBegin(GL_POINTS);
    for(int i= 0; i < particles.size(); ++i)
    {
        glColor3fv(reinterpret_cast<const GLfloat*>(&particles[i]->color()));
        glVertex3fv(reinterpret_cast<const GLfloat*>(&particles[i]->position()));
    }
    glEnd();
    glEnable(GL_LIGHTING);
    glPointSize(1.0);
}

void Fluid::update()
{
	engine->update();
}

void Fluid::crash()
{
    boxM.setX( boxM.x()*8 );
    engine->updateMemory();
}

void Fluid::drawBox()
{
    glDisable(GL_LIGHTING);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glBegin(GL_TRIANGLE_STRIP);
    {
        glColor3f(0.0, 1.0, 0.0);
        glVertex3f( boxm.x(), boxm.y(), boxM.z());
        glVertex3f( boxM.x(), boxm.y(), boxM.z());
        glVertex3f( boxm.x(), boxM.y(), boxM.z());
        glVertex3f( boxM.x(), boxM.y(), boxM.z());
        glVertex3f( boxm.x(), boxM.y(), boxm.z());
        glVertex3f( boxM.x(), boxM.y(), boxm.z());
        glVertex3f( boxm.x(), boxm.y(), boxm.z());
        glVertex3f( boxM.x(), boxm.y(), boxm.z());
        glVertex3f( boxm.x(), boxm.y(), boxM.z());
        glVertex3f( boxM.x(), boxm.y(), boxM.z());
    }
    glEnd();
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
    glEnable(GL_LIGHTING);
}
